<!DOCTYPE html><title>MIS processess permissions and the CTS</title>
<h1>MIS processess permissions and the CTS</h1>
<p>The Google CTS has a test that checks for unknown processes running as root.
The test is implemented in RootProcessScanner.java, which inspects
/proc/*/status and matches that with a short list of Google-approved process
names. Any process running as root that is not on that list is flagged as a CTS
failure. Those failures either have to be corrected or an exception must be
granted by Google.</p>
<p>In order for a MIS component to not run as root, it will have to either run as
one of the Android predefined users (which are listed in
system/core/include/private/android_filesystem_config.h) or as a separate user
created for the component. It has been suggested that the pre-defined user
"radio" should be used, but as will be seen from the analysis, "system" seems
more appropriate.</p>
<h2>The traditional Unix approach</h2>
<p>The traditional way of writing privileged Unix daemons involves starting them
as root (either by having the root user start them, or by having the binary
itself owned by root and setting its setuid bit), then have the process open
the resources it needs, and finally change user ID to that of a non-privileged
user.</p>
<p>This only works when the daemon can open all required resources as startup. If
the process needs to perform privileged operations that cannot be done at
startup, then the process would not drop its privileges, but instead keep
running as root. This is of course very risky, since any attack that yields
arbitrary code execution then yields root access for the attacker. The problem
can be mitigated via privilege separation, where the few operations that
require root access are handled by a small server from which an unprivileged
process can request services.</p>
<h2>Capabilities</h2>
<p>Since version 2.2, the Linux kernel has slowly been moving from the traditional
Unix security model with a root user capable of every operation in the system,
to a more fine-grained one based on set of separate capabilities. When a
process calls a privileged syscall, instead of checking whether the process is
running with effective user ID 0, the kernel checks whether the process has
some specific capability in its effective capability set. For instance,
connecting to CAIF requires the capability CAP_NET_ADMIN or CAP_SYS_ADMIN.</p>
<p>The new way of writing privileged Linux daemons is to use capabilities. The
process is given a set of permissible capabilities, that it then add or remove
to its set of effective capabilities at runtime. This way, the process can
enable dangerous capabilities when performing certain operations, and then
disable them during normal operations. This is allowed as long as those
capabilities are part of the set of permissible capabilities.</p>
<p>There are four ways in which processes can gain capabilities. The first way
is by being a special process started by the kernel. This is how init etc.
get their capabilities. The second is by being started by a process that has
some capability set in its effective set that is also in its inheritable set.
The interitable set can be used to limit what binaries that are execve(2)d can
access. The third way is via extended attributes in the file system (analogous
to the traditional setuid method described above). This requires that the
kernel has file system capability support enabled, that it supports extended
attributes, and that the file system supports extended attributes. The fourth
way is via the capset system call, which lets a process that has the
CAP_SETPCAP capability modify the capability sets of a different process. This
was a transitional aid and required that the kernel did NOT have file system
capability support enabled, and the CAP_SETPCAP capability is normally masked
out via the system-wide capability bounding set, making it unavailable to all
processes.</p>
<p>The /system file system in Android has the ext4 format, which supports extended
attributes. The kernel does not, however seem to support their use. The kernel
is also recent enough to not have the transitional setcap syscalls. This
effectively leaves us with a kernel without any usable file system capability
support. The problem is compounded by the fact that the Android file system
image generation tool, make_ext4fs, does not write extended attributes to the
output image file.</p>
<p>The first way, beign a special process to the kernel, is not desirable, since
all other services are started via init, and the Modem Init Daemon and Remote
File Manager should be no different.  The third way, using file system
capabilities, is intractable due to the two forementioned problems. The fourth
way requires changing the kernel to allow the CAP_SETPCAP capability, and also
requires some process to be running with elevated capabilities in order to be
able to give capabilties to other processes. The remaining way is thus to start
as root, drop unnecessary capabilities, and switch to a different user.</p>
<h3>Capabilities and setuid</h3>
<p>When changing the user ID of a process using the setuid(2) call, the kernel
will normally drop all capability bits from all sets. This can be changed to
only dropping them from the effective set by a process calling the
PR_SET_KEEPCAPS prctl(2) before changing the user ID. After that, the process
can re-enable capabilities in the effective set when needed via capset(2)
calls, either directly or via cap_set_proc from the libcap library.</p>
<h3>Capabilities and execve(2)</h3>
<p>When executing a program, the effective capabilities set of the process will be
the intersection of the effective set before the execve(2) and the forced
capabilities in the extended attributes of the program binary. Lacking extended
attributes, execve(2)d programs get an empty set as its effective capability
set. The new permitted set of the process will be the intersection of the
permitted and inherited sets. Thus, the programs will have to enable the
capabilities. The inheritable set is not modified, though, so even when there
is a long chain of programs executing each other, a process in the end of the
chain can enable bits in its effective capabilities set that were present in
the inheritable capabilities set of the original process.</p><h1>Modem Init Daemon</h1>
<p>The Modem Init Daemon (MID) performs several operations that require elevated
privileges, listed below.</p>
<h2>Privileged operations</h2>
<h3>GPIO</h3>
<h4>Analysis</h4>
<p>The MID controls the GPIO pins via GPIO sysfs entries. These files are opened,
a value is written, and then the file is closed. The files are owned by root,
which means that the MID can not open them after droping privileges.
The following files under /sys/class/gpio are accesses only at startup:</p>
<ul>
<li>export</li>
<li>gpio&lt;n&gt;/edge</li>
<li>gpio&lt;n&gt;/active_low</li>
<li>gpio&lt;n&gt;/direction_low</li>
</ul>
<p>The following files under /sys/class/gpio are accessed at runtime:</p>
<ul>
<li>gpio&lt;n&gt;/value</li>
<li>gpio&lt;n&gt;/irq_wake</li>
<li>unexport</li>
</ul>
<h4>Solution</h4>
<p>The files that are necessary at runtime are opened at startup, before dropping
privileges, and kept open.</p>
<h3>Pad muxing</h3>
<h4>Analysis</h4>
<p>On some hardware platforms, the GPIO driver cannot be used to set the pins in
safe mode. Therefor, the MID performs that task by manually mapping the GPIO
registers and setting the bits. This requires read and write access to
/dev/mem, which is owned by root, and requires CAP_SYS_RAWIO.</p>
<h4>Solution</h4>
<p>A new driver is implemented that sets the GPIOs in safe mode. It is controlled
via a sysfs entry that the MID opens before dropping privileges.</p>
<h3>Power</h3>
<h4>Analysis</h4>
<p>The MID opens the following files under /sys/power for read/write access:</p>
<ul>
<li>wake_lock</li>
<li>wake_unlock</li>
<li>cpu_latency</li>
</ul>
<p>The wake_* files are owned by the user radio and the group system, and writable
by both the user and the group. The cpu_latency file is owned by the user root
and the group root, and only writable by the user.</p>
<h4>Solution</h4>
<p>The above files are opened at startup before the MID drops privileges, and are
kept open.</p>
<h3>Reboot</h3>
<h4>Analysis</h4>
<p>The MID uses the __reboot function, which is implemented by the reboot syscall
in kernel/sys.c. That function checks for the CAP_SYS_BOOT capability.</p>
<h4>Solution</h4>
<p>Add CAP_SYS_BOOT to the effective and permitted sets.</p>
<h3>Devices</h3>
<h4>Analysis</h4>
<p>The /dev/hsi0 device is used for flashless boot and crash dump extraction. It
is owned by root, and only accessible by the root user. The /dev/ttyO2 device
is also used for flashless boot, and is owned by the radio user and group, and
only accessible for the user and group.</p>
<h4>Solution</h4>
<p>The /dev/hsi0 device should be owned by the radio user and group, and the MID
should run as the radio group.</p>
<h3>Commands</h3>
<p>The MID also runs configurable commands to perform many of its system-related
tasks. Below follows a listing of the commands used for Blaze.</p>
<p>Specific customers may have other commands in their config files. Separate
analysis will be required for those.</p>
<h4>insmod</h4>
<h5>Analysis</h5>
<p>THe insmod command is implemented by system/core/toolbox/insmod.c, and calls
the init_module syscall, implemented in kernel/kernel/module.c. That function
checks for the CAP_SYS_MODULE capability.</p>
<h5>Solution</h5>
<p>Add CAP_SYS_MODULE to the effective set that insmod gets</p>
<h4>rmmod</h4>
<h5>Analysis</h5>
<p>The rmmod command is implemented by system/core/toolbox/rmmod.c, and calls the
delete_module syscall, implemented in kernel/kernel/module.c. That function
checks for the CAP_SYS_MODULE capability.</p>
<h5>Solution</h5>
<p>Add CAP_SYS_MODULE to the effective set that rmmod gets</p>
<h4>ifconfig up</h4>
<h5>Analysis</h5>
<p>The ifcofnig command is implemented by system/core/toolbox/ifconfig.c, which
calls the SIOCSIFFLAGS ioctl on a UDP socket with ifr set to the adapter name.
This ends up in kernel/net/socket.c which delegates to net/core/dev.c, which
checks for the CAP_NET_ADMIN capability.</p>
<h5>Solution</h5>
<p>Add CAP_NET_ADMIN to the effective set that ifconfig gets and CAP_NET_RAW (?)
to create the control socket.</p>
<h4>start/stop itp-proxy rfm ril-daemon lins-proxt</h4>
<h5>Analysis</h5>
<p>The start and stop commands are implemented by system/core/toolbox/start.c and
system/core/toolbox/stop.c which set the property ctl.start or ctl.stop to the
name of the service. This is done using the libcutils function property_set,
implemented in sytem/code/libcutils/properties.c. This function sends a message
to the init property service, implemented in
system/core/init/property_service.c.</p>
<p>Properties under "ctl." are special-cased, and instead of checking the name of
the property in the property_perms table, the value that to which the property
is set is checked in the control_perms table. At present, this table only
includes an entry for the dumpstate service.  The default policy is to deny the
request, but this is overridden if the calling process is running as AID_SYSTEM
or AID_ROOT.</p>
<h5>Solution</h5>
<p>Run the MID as the AID_SYSTEM user</p>
<h4>/system/bin/mfa</h4>
<h5>Analysis</h5>
<p>The MID starts the Modem Flashing Application (MFA) to handle flashing.
Currently, the MFA is thus run as root.</p>
<h5>Solution</h5>
<p>See separate section.</p>
<h3>Wake locks</h3>
<h4>echo ITP &gt; /sys/power/wake_lock</h4>
<h5>Analysis</h5>
<p>The /sys/power/wake_lock file is owned by the user radio and group system.</p>
<h5>Solution</h5>
<p>Open the file at startup, and keep it open.</p>
<h4>echo ITP &gt; /sys/power/wake_unlock</h4>
<h5>Analysis</h5>
<p>The /sys/power/wake_unlock file is owned by the user radio and group system.</p>
<h5>Solution</h5>
<p>Open the file at startup, and keep it open.</p>
<h3>Summary</h3>
<p>The MID should run as the group radio to access the following files:</p>
<ul>
<li>/dev/hsi0</li>
<li>/dev/ttyO2</li>
</ul>
<p>The owner of the following file needs to be changed via the ueventd.omap4430.rc
mechanism:</p>
<ul>
<li>/dev/hsi0</li>
</ul>
<p>The MID should run with the following capabilities:</p>
<ul>
<li>CAP_NET_ADMIN</li>
<li>CAP_NET_RAW</li>
<li>CAP_SYS_BOOT</li>
<li>CAP_SYS_MODULE</li>
</ul>
<p>The MID will have to run as system in order to start and stop the following
services:</p>
<ul>
<li>itp-proxy</li>
<li>lins-proxy</li>
<li>rfm</li>
<li>ril-daemon</li>
</ul>
<p>The MID should open the following files and keep them open:</p>
<ul>
<li>/sys/power/wake_lock</li>
<li>/sys/power/wake_unlock</li>
<li>/sys/power/cpu_latency</li>
<li>/sys/class/gpio/gpio&lt;n&gt;/value</li>
<li>/sys/class/gpio/gpio&lt;n&gt;/irq_wake</li>
<li>/sys/class/gpio/unexport</li>
</ul>
<p>The following programs need to be modified so that they can handle being
started as user system and group radio:</p>
<ul>
<li>mfa</li>
</ul>
<p>A large number of commands, mainly in the android toolbox, do not raise their
effective capabilities.</p>
<h2>Solution</h2>
<p>The MID will at startup change to the system user and radio group, and enable
the CAP_NET_ADMIN, CAP_NET_RAW, CAP_SYS_BOOT, and CAP_SYS_MODULE capabilities
in the effective and permitted set.</p>
<p>Due to the large number of commands that would need to be made capability aware
and raise the effective bits they require, and also the nature of those
commands, the safer choice is to move the functionality into the MID. That way,
it can be ensured that they run with the correct capabilities.</p>
<p>A command parser will be implemented that replaces the current use of the
system(3) function, which calls new internal functions that perform the
operations that were previously handled though external commands.</p>
<p>A driver will be added that performs the register manipulation. The MID will
interact with it though a sysfs entry.</p>
<p>The MID will open all GPIOs and sysfs entries that it requires at runtime when
it starts, before it drops privileges. These files will then be kept open as
long as they are needed.</p>
<p>The owner and group of /dev/hsi0 will be changed in ueventd.omap4430.rc to
radio.</p><h1>Remote File Manager</h1>
<p>The Remote File Manager (RFM) server is written with the expectation that it
will be invoked as root.  It performs the standard steps of a privilegied Unix
daemon: first acquire protected resources, and then drop all privileges. It
does this by first connecting to CAIF, and then change the effective user ID to
that of a user specified on the command line. If the specified user is "root",
then the rfm server will continue running as root.</p>
<p>The RFM server has some features that only are available when running as root.
It is presently checking whether the user id is 0, instead of attempting the
operation and reporting error if it fails. This means that simply adding
capabilities will not make those features work.</p>
<p>If the rfm server is not started as root, then the system call to change the
effective user ID will fail. This will make the rfm server terminate with an
error.</p>
<h2>Privileged Operations</h2>
<h3>CAIF</h3>
<p>The RFM connects on a utility link in channel.c The connect call ends up in
caif_socket.c, which checks for CAP_SYS_ADMIN or CAP_NET_ADMIN</p>
<h3>chroot</h3>
<p>This is a root-only feature that makes the kernel prevent any access outside of
the RFM root directory. The chroot call itself ends up in kernel/fs/open.c and
requires CAP_SYS_CHROOT.</p>
<h3>Explicit isRootUser check</h3>
<p>The config.c file has a function for checking whether the rfm is running as the
user with ID 0 (i.e. root). This function and the three calls to it have to be
replaced in order to handle capabilities.</p>
<h3>setuid/setgid/setgroups</h3>
<p>If specified in options, the RFM will change user ID and group to those
specified. This requires the CAP_SYS_SETUID and CAP_SYS_SETGRP capabilities.</p>
<h3>Operations (posix.c)</h3>
<p>The file and directory operations in posix.c all work as long as the files in
the RFM root have permissions that allow the RFM server to access them. The
only exception is chown, which requires the CAP_CHOWN capability, but this is
only ever attempted if the rfm is running as root.</p>
<h3>DBus</h3>
<p>The RFM connects to dbus, and requires membership in the bluetooth group.</p>
<h2>Solutions</h2>
<p>The RFM should be started as root, and made to keep the CAP_NET_ADMIN,
CAP_SYS_CHROOT and CAP_CHOWN capabilities after switching to a normal user.</p>
<p>The checks agains user ID 0 should all be removed, and instead the RFM should
attempt the operations and report error if they fail. This way, the invoker can
determine what should be allowed by setting the capability bits.</p>
<p>The RFM should connect to DBus before dropping privileges.</p><h1>Modem Flashling Application</h1>
<p>The Modem Flashing Application (MFA) is written with the assumption that it has
all the permissions it needs to perform its operations, and that it will be
started according to the principle of least privileges.</p>
<p>It performs some operations that require privileges, which are listed below.</p>
<h2>Privileged operations</h2>
<h3>Device access</h3>
<h4>Analysis</h4>
<p>The MFA accesses the /dev/hsi0 and /dev/ttyO2 devices.  The /dev/hsi0 device is
owned by root, and only accessible by the root user. The /dev/ttyO2 device is
owned by the radio user and group, and only accessible for the user and group.</p>
<h4>Solution</h4>
<p>The /dev/hsi0 device should be owned by the radio user and group, and the MFA
should run as the radio group.</p>
<h3>File access</h3>
<h4>Analysis</h4>
<p>The MFA accesses files under /data/ste/modem, and needs to be able to create
new files there. The /data/ste/modem directory is owned by the system user
and group, and only wriable by the user and group.</p>
<h4>Solution</h4>
<p>The MFA should run as the system user</p>
<h2>Solutions</h2>
<p>The MFA should be started as the system user and the radio group.</p><h1>Conclusion</h1>
<p>By making the MID run as the system user and the radio group, most operations
that are needed by the MID and the MFA are handled. For some operations, the
MID will require special capability bits, and for pad muxing, a driver is
necessary. The RFM needs to re-arrange its startup order to connect to DBus
before dropping privileges, and to keep some capabilities after dropping
privileges.</p>
<p>With these changes, the MIS will not have processes running as root after
startup, which means that it will pass the RootProcessScanner test in the CTS.</p>